package cn.lg.soar.mvc.manager;

import cn.lg.soar.common.util.listener.SpringUtils;
import cn.lg.soar.mvc.enums.SseEventTypeEnum;
import cn.lg.soar.mvc.event.SseEvent;
import cn.lg.soar.mvc.model.ClientInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.Collection;

/**
 * @author luguoxiang 469599794@qq.com
 * @Date: 2023/11/23 17:50
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public class SseManager extends AbstractClientInfoManager<SseEmitter> implements IClientNoticeService {
    private static final Logger logger = LoggerFactory.getLogger(SseManager.class);
    private final static String JOIN = "::";

    @Override
    public Collection<Long> sendMsgByUser(String topic, String message, Collection<Long> userIds) {
        return sendMsgByUser(topic + JOIN + message, userIds);
    }

    @Override
    public boolean sendMsgByClient(String topic, String message, String clientId) {
        return sendMsgByClient(topic + JOIN + message, clientId);
    }

    /**
     * 广播消息
     * @param message 消息
     */
    @Override
    public Collection<Long> sendMsgAll(String topic, String message) {
        return sendMsgAll(topic + JOIN + message);
    }

    /**
     * 创建连接
     * @param userId
     * @return
     */
    public SseEmitter open(Long userId, String clientId){
        //设置超时时间，0表示不过期，默认是30秒，超过时间未完成会抛出异常
        SseEmitter sseEmitter = new SseEmitter(600_000L);
        // 超时关闭
        sseEmitter.onTimeout(() -> close(sseEmitter));
        sseEmitter.onError((e) -> {
            // 发布事件
            SpringUtils.publishEvent(new SseEvent(SseEventTypeEnum.error, clientId, size()));
        });
        // 加入map
        put(userId, clientId, sseEmitter);
        // 发布事件
        SpringUtils.publishEvent(new SseEvent(SseEventTypeEnum.open, clientId, size()));
//        // 发布广播
        sendMsgAll("online", String.valueOf(size()));
        return sseEmitter;
    }

    /**
     * 关闭连接
     * @param userId
     */
    public void close(SseEmitter client){
        ClientInfo<SseEmitter> clientInfo = remove(client);
        if (clientInfo == null) {
            return;
        }
        // 关闭
        clientInfo.getClient().complete();
        // 发布事件
        SpringUtils.publishEvent(new SseEvent(SseEventTypeEnum.open, clientInfo.getClientId(), size()));
        // 发布广播
        sendMsgAll("online", String.valueOf(size()));
    }

    public void close(String clientId) {
        ClientInfo<SseEmitter> clientInfo = getClientInfo(clientId);
        if (clientInfo != null) {
            close(clientInfo.getClient());
        }
    }

    @Override
    protected boolean doSendMsg(SseEmitter client, String message) {
        try {
            client.send(message);
            return true;
        } catch (IOException e) {
            logger.error("sse消息发送失败", e);
            return false;
        }
    }

}
